#include "CustomMsg.h"
#include "CustomMutex.h"
#include "MainWindow.h"
#include "ui_mainwindow.h"

#include <QQueue>
#include <QThread>
#include <QWaitCondition>

CustomMutex gMutex;
QQueue<CustomMsg> gMsgQueue;

#define GLOCK() gMutex.lock(__FILE__,__LINE__);
#define GUNLOCK() gMutex.unlock(__FILE__,__LINE__);

class ThreadProduce : public QThread{

private:
    QWaitCondition mCondEmpty;
protected:
    void run(){
        int no = 0;
        while(!isInterruptionRequested()){
            qDebug()<< " ThreadProduce Run for the  " << QString::number(no) << " time ";
            GLOCK();

            qDebug()<< " qDebug wait for msg queue empty";

            //等待唤醒
            mCondEmpty.wait(&gMutex);

            //外部函数可以唤醒等待，然后中止线程
            if(isInterruptionRequested()){
                this->quit();
            }

            CustomMsg msg;
            msg.msgType = 1;
            msg.msgNo = no;
            msg.msgData = "the " + QString::number(msg.msgNo)  + " msg";
            gMsgQueue.push_back(msg);
            GUNLOCK();

            no ++;
            QThread::sleep(1);
        }
    }
public:
    void wake(){
        mCondEmpty.wakeOne();
    }
};

class ThreadConsume : public QThread{

private:
    QWaitCondition mCondNotEmpty;

protected:
    void run(){
        int no = 0;
        while(!isInterruptionRequested()){
            qDebug()<< " ThreadConsume Run for the  " << QString::number(no) << " time ";
            GLOCK();

            if(gMsgQueue.isEmpty() || gMsgQueue.size() <= 0){
                qDebug()<< " qDebug wait for msg queue not empty";
                mCondNotEmpty.wait(&gMutex);
            }

            if(isInterruptionRequested()){
                this->quit();
            }

            CustomMsg msg = gMsgQueue.front();

            qDebug() << " consume msg msgNo: " << msg.msgNo << " msgData "  << msg.msgData;

            gMsgQueue.pop_front();
            no ++;
            GUNLOCK();

            QThread::sleep(1);
        }
    }
public:
    void wake(){
        mCondNotEmpty.wakeOne();
    }
};


ThreadProduce gThreadProduce;
ThreadConsume gThreadConsume;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_pBtnProduce = new QPushButton("Produce");
    m_pBtnConsume = new QPushButton("Consume");
    m_pHblGlobal = new QHBoxLayout;

    m_pHblGlobal->addWidget(m_pBtnProduce);
    m_pHblGlobal->addWidget(m_pBtnConsume);

    ui->centralWidget->setLayout(m_pHblGlobal);

    connect(m_pBtnProduce,SIGNAL(clicked()),this,SLOT(onBtnProduceClicked()));
    connect(m_pBtnConsume,SIGNAL(clicked()),this,SLOT(onBtnConsumeClicked()));

    gThreadProduce.start();
    gThreadConsume.start();
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::onBtnProduceClicked()
{
    gThreadProduce.wake();
}

void MainWindow::onBtnConsumeClicked()
{
    gThreadConsume.wake();
}
